Skip to content

Fix output-axis reductions and DR variance propagation - #1069

Open
kbattocchi wants to merge 4 commits into
kebatt/causal-forest-standard-errorsfrom
kebatt/numpy-reduction-fixes
Open

kbattocchi wants to merge 4 commits into
kebatt/causal-forest-standard-errorsfrom
kebatt/numpy-reduction-fixes

Conversation

@kbattocchi

@kbattocchi kbattocchi commented Sep 28, 2026 •

Copy link
Copy Markdown
Member

Summary

Following up on #1067, had Copilot audit the codebase for other places where we wrongly use a numpy operation on a whole array instead of specifying an axis.

This PR fixes the four confirmed bugs that the review found, in three logical commits:

  • Normalize output-averaged CV MSE by mean within-output target variance, rather than pooling output means into the variance. Independent outcome offsets no longer spuriously inflate model-selection scores.
  • Scope population Gaussian-mixture interval invalidation to individual outcome/treatment columns. Exclude nonfinite means/scales and nonpositive scales before solving, preserving unaffected intervals and avoiding nontermination.
  • Align DR sample_var vectors and singleton columns with final targets, avoiding unintended sample-by-sample broadcasting and fitting failures.
  • Propagate DR outcome variance separately for each treatment-versus-control contrast using its squared observed-outcome derivative. Observations from unrelated treatment arms contribute zero propagated variance rather than inflating standard errors.

Includes regression tests and directly related documentation. Both separate and multitask DR final models are covered, including trimming, heterogeneous weights/propensities, and summarized-versus-expanded observation equivalence.

@kbattocchi
kbattocchi added this pull request to stack #1070 September 28, 2026 19:44
@kbattocchi
kbattocchi force-pushed the kebatt/numpy-reduction-fixes branch 2 times, most recently from 366cd5b to 4ca2540 Compare October 1, 2026 19:06
@kbattocchi
kbattocchi force-pushed the kebatt/numpy-reduction-fixes branch from 4ca2540 to c37542f Compare October 20, 2026 21:16
@kbattocchi
kbattocchi force-pushed the kebatt/numpy-reduction-fixes branch 4 times, most recently from 55ec498 to 464bd8f Compare October 27, 2026 17:41
@kbattocchi
kbattocchi force-pushed the kebatt/numpy-reduction-fixes branch from 464bd8f to 46bb96a Compare October 27, 2026 19:25
@kbattocchi
kbattocchi requested review from fverac and a balanced review from Copilot and removed request for Copilot October 27, 2026 20:02

Copilot AI left a comment

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Warning

Copilot couldn't run its full agentic review because it didn't start before the timeout. Make sure your repository has a runner available, or add a copilot-code-review.yml file specifying one with the runs-on attribute. See the docs for more details.

Copilot review overview

2 open issues
What changed in this PR

Fixes several axis/broadcasting bugs affecting model-selection scoring, population mixture confidence intervals, and DRLearner variance propagation—plus adds regression tests for the corrected behaviors.

Changes:

  • Normalize ElasticNetCV/LassoCV selector “R²” scoring by mean per-output variance (instead of pooled variance).
  • Make Gaussian-mixture CI computation invalidate only affected outcome/treatment columns and avoid nontermination on invalid normal params.
  • Correct DRLearner final-stage sample_var shape handling and propagate outcome variance per treatment-vs-control contrast.
File Description
econml/​sklearn_extensions/​model_selection.py Fixes selector score normalization for multi-output targets.
econml/​inference/​_inference.py Refines mixture PPF invalidation to column-level and updates docstring.
econml/​dr/​_drlearner.py Fixes DR sample_var shape validation and per-contrast variance propagation.
econml/​tests/​test_model_selection.py Adds regression tests for selector scoring invariance to output offsets/reordering.
econml/​tests/​test_inference.py Adds tests for mixture CI behavior with zero/invalid scales per column.
econml/​tests/​test_drlearner.py Adds tests for DR final-stage sample_var shapes and variance equivalence.

Review effort: Lite

Comment on lines +1582 to +1589
# Invalid normal parameters prevent convergence. Exclude only the affected
# outcome/treatment columns from the solver.
invalid = np.any((stderr <= 0) | ~np.isfinite(stderr) | ~np.isfinite(mean), axis=0)
if np.any(invalid):
result = np.full(shape(mean)[1:], np.nan)
if not np.all(invalid):
result[~invalid] = self._mixture_ppf(alpha, mean[:, ~invalid], stderr[:, ~invalid], tol)
return result

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This indexing is valid: NumPy's boolean masks consume as many consecutive axes as the mask has dimensions. Here invalid.shape == mean.shape[1:], so mean[:, ~invalid] preserves the sample axis and selects valid outcome/treatment pairs, returning (m, n_valid). result[~invalid] maps the results back to the original output shape. Explicit flattening would be equivalent, not a fix.

I verified the selection/assignment directly and executed all 34 existing mixture regression cases against this PR's helper, including multidimensional outputs and reordered invalid columns; they pass. See NumPy's boolean-indexing rules. Keeping the implementation unchanged.

Comment thread econml/inference/_inference.py Outdated
Get the confidence interval of the point estimate of each treatment on each outcome for sample X.

An outcome/treatment interval is NaN if any of its sample means or standard errors
is nonfinite, or any standard error is nonpositive. Other intervals are unaffected.

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Clarified in d517e90: “An outcome/treatment interval is NaN if any sample mean or standard error is nonfinite, or any standard error is nonpositive. Other intervals are unaffected.” This avoids the ambiguous agreement without changing behavior.

@kbattocchi
kbattocchi marked this pull request as ready for review November 2, 2026 18:10
@kbattocchi
kbattocchi force-pushed the kebatt/numpy-reduction-fixes branch from d517e90 to 9602a0b Compare November 2, 2026 18:10
kbattocchi and others added 4 commits November 3, 2026 17:24
Normalize output-averaged CV MSE by mean within-output variance so independent outcome offsets do not inflate selector scores. Preserve the fast approximation and existing unweighted normalization policy.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Keith Battocchi <kebatt@microsoft.com>
Keep NaN intervals local to outcome/treatment columns with nonpositive scales or nonfinite normal parameters. Exclude invalid columns before solving so unaffected intervals retain their values and shape without risking nontermination.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Keith Battocchi <kebatt@microsoft.com>
Align vector and singleton-column sample variances with final targets, and apply the squared observed-outcome derivative separately for each treatment-versus-control contrast. This avoids quadratic broadcasting and excludes variance from unrelated treatment arms. Cover both final-model modes, trimming, weighted summaries, and expanded-observation covariance equivalence.

Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Keith Battocchi <kebatt@microsoft.com>
Co-authored-by: Copilot App <223556219+Copilot@users.noreply.github.com>
Signed-off-by: Keith Battocchi <kebatt@microsoft.com>
@kbattocchi
kbattocchi force-pushed the kebatt/numpy-reduction-fixes branch from 9602a0b to cc33889 Compare November 3, 2026 22:24

This branch has not been deployed

No deployments
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants